#include <transfert-server.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <netdb.h>
#include <signal.h>

#include <log.h>
#include <config-server.h>
#include <lock.h>
#include <constants.h>

void sigchild_handler(){
	int status;
	wait(&status);
	siginterrupt(SIGCHLD, 0);
	signal(SIGCHLD, sigchild_handler);
	return;
}

int SocketInit(){
	int ret;	
	struct sockaddr_in serveur;
	socketDescriptor=socket(AF_INET,SOCK_STREAM,0);

	serveur.sin_family=AF_INET;
	serveur.sin_addr.s_addr=htons(INADDR_ANY);
	serveur.sin_port=htons(4212);

	ret=bind(socketDescriptor, (struct sockaddr *)&serveur, sizeof(serveur));
	if(ret<0){
		LogError("BIND : Impossible d'initialiser le socket du serveur", 2);
	}
	ret=listen(socketDescriptor,10);
}

void TransmitReport(int sd){
	int fd;
	struct stat fileStat;
	

	fd = open(SERVER_REPORT, O_RDONLY);
	fstat(fd, &fileStat);
	
	sendfile(sd, fd, NULL, fileStat.st_size);
	close(sd);
}

void BuildReport(){
	remove(SERVER_REPORT);
	char command[128] = SERVER_BUILDER_SD;
	strcat(command, " > ");
	strcat(command, SERVER_REPORT);
	if(system(command)==-1){
		remove(SERVER_REPORT);
	}
}

void SendReport(int sd){
	write(sd, "*OKBG", sizeof(char)*6);

	while(IsFileUnlocked(SERVER_BUILDING)==0){
		usleep(15);
	}
	LockAFile(SERVER_BUILDING);
	
	if(IsFileUnlocked(SERVER_REPORT)){
		BuildReport();
		LockAFile(SERVER_REPORT);
	}

	UnlockAFile(SERVER_BUILDING);
	UnlockAFile(SERVER_REPORT);

	struct stat fStat;
	stat(SERVER_REPORT, &fStat);
	if(!FileExists(SERVER_REPORT)){
		LogWarning("La création d'un fichier de rapport a échoué.");
		write(sd, "*NOOK", strlen("*NOOK")*sizeof(char));
		return;
	}
	char fSize[32] = "*TRAN";
	sprintf(fSize+strlen(fSize), "%.ld", fStat.st_size );
	
	write(sd, fSize, strlen(fSize)*sizeof(char));
	
	char buffer[5];
	read(sd, buffer, 5*sizeof(char));
	if(strncmp(buffer, "*OKGO", 5)!=0){
		return;
	}
	
	TransmitReport(sd);
}

void ListenLoop(){
	int nsd, ret;
	int client_size=sizeof(clientAddress);
    signal(SIGCHLD, sigchild_handler);
	for(;;){
		nsd=accept(socketDescriptor, (struct sockaddr_in *)&clientAddress, &client_size);

		if(nsd<0){
			LogError("Reception d'une requête impossible",3);
		} else {
			char buf[6];

			ret=read(nsd, buf, sizeof(buf));
			buf[5] = '\0';
			if(ret<0){
				LogError("Connexion perdue : Une requête n'a pas été traitée.", 2);
			}else if(buf[0]=='*'){
				if(strncmp(buf, "*TTCN", 5)==0){
					write(nsd, "*CNOK", sizeof(char)*6);
				}else if(strncmp(buf, "*GETR", 5)==0){
					int pid = fork();
					switch(pid){
						case -1:{
							LogWarning("Création échouée d'un fork pour l'envoi de fichier");
							break;
						}
						case 0:{
							SendReport(nsd);
							exit(0);
						}
					}
					
				}
			}
		}
	}
}
